import { _decorator, Component, macro, Node, RigidBodyComponent, Vec3 } from 'cc';
import { monsterModel } from './monsterModel';
import { monsterBloodBar } from './monsterBloodBar';
import { constant } from '../framework/constant';
import { characterRigid } from './characterRigid';
import { gameManager } from './gameManager';
import { poolManager } from '../framework/poolManager';
import { audioManager } from '../framework/audioManager';
import { effectManager } from '../framework/effectManager';
import { localConfig } from '../framework/localConfig';
import { util } from '../framework/util';
const { ccclass, property } = _decorator;

@ccclass('monster')
export class monster extends Component {



    /** 怪物动画组件播放脚本 */
    public scriptMonsterModel: monsterModel = null!;
    /** 怪物是否正在移动 */
    public isMoving: boolean = false;
    /** 关联的血条脚本 */
    public scriptBloodBar: monsterBloodBar = null!;
    /** 血量提示方向 */
    public bloodTipDirection: number = constant.BLOOD_TIP_DIRECTION.LEFT_UP;
    /** 技能信息 */
    public skillInfo: any = null!;
    /** 所有拥有的技能信息 */
    public allSkillInfo: any = null!;
    /** 怪物在base表里面对应数据 */
    public baseInfo: any = null!;
    /** 怪物在当前层级的配置数据 */
    public layerInfo: any = null!;
    /** 当前攻击速度 */
    public curAttackSpeed: number = 0;
    /** 预警技能脚本 */
    public scriptWarning: any = null!;
    /** 攻击朝向 */
    public attackForward: Vec3 = new Vec3();
    /** 技能即将攻击的位置 */
    public attackPos: Vec3 = new Vec3();
    public rigidComMonster: RigidBodyComponent = null!;
    public scriptCharacterRigid: characterRigid = null!;
    public set curMoveSpeed(v: number) {
        this._curMoveSpeed = v;
        this.scriptCharacterRigid.initSpeed(v, gameManager.moveSpeedAddition);
    }

    public get curMoveSpeed() {
        return this._curMoveSpeed;
    }

    public set isDie(v: boolean) {
        this._isDie = v;

        if (this._isDie) {
            this.showDie();
        }
    }




    public get isDie() {
        return this._isDie;
    }

    /** 是否死亡 */
    protected _isDie: boolean = false;
    /** 距离上次被攻击的时长 */
    protected _curAttackInterval: number = 0;
    /** 是否被玩家击中 */
    protected _isHitByPlayer: boolean = false;
    /** 是否已经初始化血条 */
    protected _isInitBloodBar: boolean = false;
    /** 怪物血条距离人物位置偏差 */
    protected _bloodTipOffsetPos: Vec3 = new Vec3(0, 50, 0);
    /** 怪物的血条被攻击后才会显示，且如果3秒未被攻击则会隐藏 */
    protected _hideBloodCountDown: number = 3;
    /** 受击特效位置 */
    protected _hitEffectPos: Vec3 = new Vec3(0, 0.2, 0);
    /** 是否允许攻击 */
    protected _isAllowToAttack: boolean = false;
    /** 怪物和玩家间距 */
    protected _playerMonsterOffset: Vec3 = new Vec3();
    /** 当前Y分量旋转角度 */
    protected _curAngleY: number = 0;
    /** 水平移动距离 */
    protected _horizontal: number = 0;
    /** 垂直移动距离 */
    protected _vertical: number = 0;
    /** 冰冻伤害倒计时 */
    protected _iceDamageCountDown: number = 0;
    /** 灼烧伤害倒计时 */
    protected _fireDamageCountDown: number = 0;
    /** 当前是否停止攻击,且原地跑 */
    protected get _isStopAttack() {
        return !this.isDie && !this.scriptMonsterModel.isIdle && !this.scriptMonsterModel.isAttacking && !this.scriptMonsterModel.isHitting && this._prevMoveWorPos.equals(this.node.worldPosition, 0.01);
    }
    /** 技能特效节点 */
    protected _ndMonsterSkill: Node = null!;
    /** 当前技能索引 */
    protected _skillIndex: number = 0;
    /** 怪物和玩家之间的最小距离 */
    protected _minLength: number = 3;
    /** 当前移动速度 */
    protected _curMoveSpeed: number = 0;

    //移动相关

    /** 移动方式 */
    protected _moveMode: number = 0;
    /** 移动模式 */
    protected _movePattern: number = 0;
    /** 两次移动间隔,为0表示一直移动) */
    protected _moveFrequency: number = 0;
    /** 和玩家之间的向量差 */
    protected _offsetPos: Vec3 = new Vec3();
    /** 和玩家之间的向量差 */
    protected _offsetPos_2: Vec3 = new Vec3();
    /** 和玩家的最小间距 */
    protected _mixOffset: Vec3 = new Vec3(1, 0, 1);
    /** 下一步的目标位置 */
    protected _targetWorPos: Vec3 = new Vec3();
    /** 是否旋转 */
    protected _isPlayRotate: boolean = false;
    /** 当前旋转的角度 */
    protected _curAngle: Vec3 = new Vec3()
    /** 怪物角度 */
    protected _curAngle_2: Vec3 = new Vec3();
    /** 临时变量，怪物角度 */
    protected _tempAngle: Vec3 = new Vec3();
    /** 旋转方向 */
    protected _rotateDirection: Vec3 = new Vec3();
    /** 朝向 */
    protected _forWard: Vec3 = new Vec3();
    /** 烟雾特效 */
    protected _ndRunSmokeEffect: Node = null!;
    /** 怪物开始角度 */
    protected _originAngle: Vec3 = new Vec3(0, -90, 0);
    /** 目标旋转角度 */
    protected _targetAngle: Vec3 = new Vec3();
    /** 每40ms刷新一次 */
    protected _checkInterval: number = 0.04;
    /** 当前累积时间 */
    protected _currentTime: number = 0;
    protected _ndBody: Node = null!;
    /** 当前怪物移动位置 */
    protected _curMoveWorPos: Vec3 = new Vec3();
    /** 是否到达 */
    protected _isArrived: boolean = false;
    /** 检查当前是否移动时间间隔 */
    protected _checkMoveInterval: number = 0;
    /** 之前怪物的移动坐标 */
    protected _prevMoveWorPos: Vec3 = new Vec3();
    /** 每次移动的单位向量 */
    protected _moveUnit: Vec3 = new Vec3();
    /** 达到最小距离的1.1倍视为进入最小距离 */
    protected _minLengthRatio: number = 1.1;
    /** 每次随机移动位置最多计算次数 */
    protected _randomMoveTryTimes: number = 5;

    public init(baseInfo: any, layerInfo: any) {
        this.baseInfo = baseInfo;
        this.layerInfo = layerInfo;
        this.isDie = false;

        this.recycleWarning();

        this._ndBody = this.node.getChildByName("body") as Node;
        this.scriptCharacterRigid = this.node.getComponent(characterRigid) as characterRigid;

        if (!this.rigidComMonster) {
            this.rigidComMonster = this.node.getComponent(RigidBodyComponent) as RigidBodyComponent;
        }
        this.rigidComMonster.clearState();

        this.scriptMonsterModel = this._ndBody.getComponent(monsterModel) as monsterModel;
        this.scriptMonsterModel.playAni(constant.MONSTER_ANI_TYPE.IDLE, true);

        this._curAttackInterval = 0;
        this._isHitByPlayer = false;
        this._isInitBloodBar = false;
        this._isAllowToAttack = false;
        this._isArrived = false;
        this._checkMoveInterval = 0;
        this._iceDamageCountDown = 0;
        this._fireDamageCountDown = 0;
        this._ndMonsterSkill = null!;
        this._skillIndex = 0;
        this._moveUnit = new Vec3();
        // this._isCloseFighting = false;
        this._movePattern = layerInfo.movePattern ? layerInfo.movePattern : this.baseInfo.movePattern;

        this.scriptBloodBar = null!;

        this._refreshSkill();

        this.scriptMonsterModel.scriptMonster = this;

        this.curAttackSpeed = this.baseInfo.attackSpeed;
        this.curMoveSpeed = this.baseInfo.moveSpeed;

        this._getMinLength();
    }

    public recycleWarning() {
        //回收预警节点
        if (this.scriptWarning) {
            if (this.scriptWarning.node.parent) {
                poolManager.instance.putNode(this.scriptWarning.node);
            }
            this.scriptWarning = null!;
        }
    }

    /**
     * 怪物阵亡
     *
     * @memberof Monster
     */
    public showDie() {
        this.scriptCharacterRigid.stopMove();

        this.recycleWarning();

        audioManager.instance.playSound(`${this.node.name}Die`);

        let sound = '';
        if (this.node.name === "aula") {
            sound = constant.SOUND.AULA_DIE;
        } else if (this.node.name === "boomDragon") {
            sound = constant.SOUND.BOOM_DRAGON_DIE;
        } else if (this.node.name === "hellFire") {
            sound = constant.SOUND.HELL_FIRE_DIE;
        } else if (this.node.name === "magician") {
            sound = constant.SOUND.MAGICIAN_DIE;
        } else if (this.node.name === "dragon") {
            sound = constant.SOUND.DRAGON_DIE;
        }

        audioManager.instance.playSound(sound);

        effectManager.instance.showRewardBounce(this.node, "gold/gold", this.baseInfo.goldNum, () => {
            if (this.baseInfo.heartDropRate >= Math.random()) {
                effectManager.instance.showRewardBounce(this.node, "heart/heart", 1);
            }
        });

        //检查玩家是否拥有嗜血技能：主角击杀敌人时回复自身生命上限2%的生命值。
        if (gameManager.scriptPlayer.isBloodthirsty) {
            let bloodNum = gameManager.scriptPlayer.curHpLimit * 0.02;
            gameManager.scriptPlayer.addBlood(bloodNum);
        }

        this.scriptMonsterModel.playAni(constant.MONSTER_ANI_TYPE.DIE, false, () => {
            if (this.isDie) {
                this.scriptBloodBar = null!;
                poolManager.instance.putNode(this.node);
            }
        });
    }

    /**
     * 刷新当前使用技能
     *
     * @private
     * @memberof Monster
     */
    protected _refreshSkill() {
        this.allSkillInfo = this.layerInfo.skill === "" ? [] : this.layerInfo.skill.split("#");
        if (this.allSkillInfo.length) {
            this._skillIndex = this._skillIndex >= this.allSkillInfo.length ? 0 : this._skillIndex;
            let skillID = this.allSkillInfo[this._skillIndex];
            this.skillInfo = localConfig.instance.queryByID("monsterSkill", skillID);
            this._skillIndex += 1;
        }
    }

    /**
     * 获取怪物和玩家之间的最小距离
     *
     * @memberof Monster
     */
    protected _getMinLength() {
        if (this.node.name === "aula") {
            this._minLength = 2;
        } else if (this.node.name === "boomDragon") {
            this._minLength = 2;
        } else if (this.node.name === "hellFire") {
            this._minLength = 2.5;
        } else if (this.node.name === "magician") {
            this._minLength = 2.5;
        } else if (this.node.name === "dragon") {
            this._minLength = 5;
        }
    }

    /**
     * 先移动
     *
     * @private
     * @memberof Monster
     */
    protected _monsterMove() {
        if (this.isDie) {
            return;
        }

        if (!this._isAllowToAttack) {
            this._isAllowToAttack = true;
        }

        if (this._movePattern === constant.MONSTER_MOVE_PATTERN.NO_MOVE) {
            //不移动，原地攻击玩家
            this._lookAtTargetWorPos();
        } else if (this._movePattern === constant.MONSTER_MOVE_PATTERN.RANDOM) {
            this._randomMoveTryTimes = 5;
            this._getRandomMovePos();
        } else if (this._movePattern === constant.MONSTER_MOVE_PATTERN.FORWARD_PLAYER) {
            //面向玩家移动：先面向玩家，再移动，然后攻击
            this._lookAtTargetWorPos();
            Vec3.subtract(this._offsetPos, gameManager.ndPlayer.worldPosition, this.node.worldPosition);
            this._offsetPos.y = 0;

            let offsetLength = util.getTwoNodeXZLength(this.node, gameManager.ndPlayer);
            //当怪物和玩家小于2个最小距离之和或者大于一个最小距离且小于两个最小距离，进行移动
            if (offsetLength > this._minLength * 2 || (offsetLength > this._minLength && offsetLength < this._minLength * 2)) {
                //单位向量
                Vec3.normalize(this._moveUnit, this._offsetPos);
                Vec3.multiplyScalar(this._offsetPos, this._moveUnit, this._minLength);

                if (offsetLength > this._minLength * 2) {
                    //向玩家移动2个单位向量
                    Vec3.add(this._targetWorPos, this.node.worldPosition, this._offsetPos);
                } else {
                    Vec3.subtract(this._targetWorPos, gameManager.ndPlayer.worldPosition, this._offsetPos);
                }

                this._targetWorPos.set(util.toFixed(this._targetWorPos.x), util.toFixed(this.node.worldPosition.y), util.toFixed(this._targetWorPos.z));
                this.isMoving = true;
            } else {
                //否则原地进行攻击
                this.playAction({ action: constant.MONSTER_ACTION.STOP_MOVE });
            }
        }
    }

    /**
     * 怪物面向目标的世界坐标
     *
     * @private
     * @memberof Monster
     */
    protected _lookAtTargetWorPos(targetWorPos?: Vec3) {
        let screenPos1 = gameManager.mainCamera?.worldToScreen(gameManager.ndPlayer.worldPosition) as Vec3;
        let screenPos2 = gameManager.mainCamera?.worldToScreen(this.node.worldPosition) as Vec3;
        if (targetWorPos) {
            screenPos1 = gameManager.mainCamera?.worldToScreen(targetWorPos) as Vec3;
        }
        Vec3.subtract(this._playerMonsterOffset, screenPos1, screenPos2);
        let angleY = Math.round(Math.atan2(this._playerMonsterOffset.y, this._playerMonsterOffset.x) * 180 / Math.PI);
        // if (angleY !== this._curAngleY) {
        this.playAction({ action: constant.MONSTER_ACTION.MOVE, value: angleY });
        // }
    }


    /**
     * 怪物行为
     *
     * @param {*} obj
     * @memberof Player
     */
    public playAction(obj: any) {
        switch (obj.action) {
            case constant.MONSTER_ACTION.MOVE:
                let angle = obj.value + 135;

                let radian = angle * macro.RAD;
                this._horizontal = Math.round(Math.cos(radian) * 1);
                this._vertical = Math.round(Math.sin(radian) * 1);
                this.isMoving = true;

                this._curAngleY = obj.value;
                this._curAngleY = this._curAngleY < 0 ? this._curAngleY + 360 : this._curAngleY > 360 ? this._curAngleY - 360 : this._curAngleY;

                this._prevMoveWorPos.set(this.node.worldPosition);
                break;
            case constant.MONSTER_ACTION.STOP_MOVE:
                this._horizontal = 0;
                this._vertical = 0;

                if (gameManager.ndPlayer) {
                    this._attackPlayer();
                } else {
                    this.scriptMonsterModel.playAni(constant.MONSTER_ANI_TYPE.IDLE, true);
                }

                this.isMoving = false;
                this.scriptCharacterRigid.stopMove();
                break;
            default:
                break;
        }
    }


    /**
     * 攻击玩家
    */
    protected _attackPlayer() {
        if (gameManager.scriptPlayer.isDie || this.scriptMonsterModel.isAttacking) {
            return;
        }

        Vec3.subtract(this._offsetPos_2, gameManager.ndPlayer.worldPosition, this.node.worldPosition);
        let length = this._offsetPos_2.length();
        this.attackForward = this._offsetPos_2.normalize().negative();
        this.attackPos.set(gameManager.ndPlayer.worldPosition);

        //预警
        if (this.allSkillInfo.length && this.skillInfo && this.skillInfo.warning) {
            let scale = 1;
            if (this.skillInfo.ID === constant.MONSTER_SKILL.FIRE_BALL) {
                scale = 0.1;
            } else if (this.skillInfo.ID === constant.MONSTER_SKILL.FIRE_BALL_BIG) {
                scale = 0.4;
            } else if (this.skillInfo.ID === constant.MONSTER_SKILL.LASER) {
                scale = 3;
            } else if (this.skillInfo.ID === constant.MONSTER_SKILL.ENERGY_BALL) {
                scale = length;
            }

            //回收预警节点
            this.recycleWarning();

            effectManager.instance.showWarning(this.skillInfo.warning, scale, this, () => {
                this.playAttackAni();
            });
        } else {
            this.playAttackAni();
        }
    }

    /**
     * 播放攻击动画
     *
     * @protected
     * @memberof Monster
     */
    public playAttackAni() {
        let attackAniName = constant.MONSTER_ANI_TYPE.ATTACK;
        if (this.baseInfo.resName === "hellFire") {
            //hellFire的攻击动画有两个，其他小怪动画只有一个
            if (!this.allSkillInfo.length) {
                //近战
                attackAniName = constant.MONSTER_ANI_TYPE.ATTACK_1;
            } else {
                //远程
                attackAniName = constant.MONSTER_ANI_TYPE.ATTACK_2;
            }
        }

        //远程
        if (this.allSkillInfo.length) {
            this.scriptMonsterModel.playAni(attackAniName, false, () => {
                if (!this.isDie && !this.scriptMonsterModel.isHitting) {
                    this.scheduleOnce(() => {
                        this._monsterMove()
                    }, this.baseInfo.moveFrequency)
                }
            });
        } else {
            //近战
            let offsetLength = util.getTwoNodeXZLength(this.node, gameManager.ndPlayer);
            if (offsetLength <= this._minLength * this._minLengthRatio) {
                this.scriptMonsterModel.playAni(attackAniName, false, () => {
                    if (!this.isDie && !this.scriptMonsterModel.isHitting) {
                        this.scheduleOnce(() => {
                            this._monsterMove()
                        }, this.baseInfo.moveFrequency)
                    }
                });
            } else {
                if (!this.isDie && !this.scriptMonsterModel.isHitting) {
                    this.scheduleOnce(() => {
                        this._monsterMove()
                    }, this.baseInfo.moveFrequency)
                }
            }
        }
    }


    private _getRandomMovePos() {
        this._randomMoveTryTimes -= 1;
        //随机移动：先以怪物圆环区间(1, minLength)随机移动,再朝向玩家,然后攻击
        let x = util.getRandom(1, 3) * util.getRandomDirector();
        let z = util.getRandom(1, 3) * util.getRandomDirector();
        // console.log("###随机移动", x, z);
        this._targetWorPos.set(util.toFixed(this.node.worldPosition.x + x), util.toFixed(this.node.worldPosition.y), util.toFixed(this.node.worldPosition.z + z));

        let offsetLength = util.getTwoPosXZLength(this._targetWorPos.x, this._targetWorPos.z, gameManager.ndPlayer.worldPosition.x, gameManager.ndPlayer.worldPosition.z);
        //当目标位置和玩家大于最小距离，进行移动
        if (offsetLength > this._minLength) {
            Vec3.subtract(this._offsetPos, this._targetWorPos, this.node.worldPosition);
            this._offsetPos.y = 0;
            Vec3.normalize(this._moveUnit, this._offsetPos);

            this._lookAtTargetWorPos(this._targetWorPos);
            this.isMoving = true;
            this._isArrived = false;
        } else {
            //否则尝试5次随机移动，都没合适的位置则进行进攻
            if (this._randomMoveTryTimes <= 0) {
                // console.log("###随机移动", this._randomMoveTryTimes);
                this.playAction({ action: constant.MONSTER_ACTION.STOP_MOVE });
            } else {
                this._getRandomMovePos();
                // console.log("###随机移动", this._randomMoveTryTimes);
            }
        }
    }

}


